#include "textedit.h"
#include <QFileInfo>
#include <QTextStream>
#include <QMessageBox>
#include <QFileDialog>
#include <QTextDocumentWriter>
#include <QCloseEvent>
#include <QTextBlock>
#include <QTextList>

// 静态成员初始化：用于生成新文档的默认名称计数器
int TextEdit::docNo = 1;

/* 构造函数
 * [功能] 创建文本编辑器实例，初始化基础属性
 * [注意] 设置WA_DeleteOnClose确保窗口关闭时自动释放内存 */
TextEdit::TextEdit(QWidget *parent)
    : QTextEdit(parent)         // 继承QTextEdit功能
    , docName("")               // 初始化文档显示名称
    , filePath("")              // 初始化文件完整路径
{
    this->setAttribute(Qt::WA_DeleteOnClose); // 自动内存管理
    connect(this->document(), &QTextDocument::contentsChange,
            this, &TextEdit::setWindowModify); // 重复连接问题！
}

// 析构函数（空实现，实际由WA_DeleteOnClose机制管理资源）
TextEdit::~TextEdit() {}

/* 窗口修改状态同步
 * [功能] 当文档内容变化时更新标题栏的*标记
 * [机制] 将窗口修改状态与文档的isModified属性绑定 */
void TextEdit::setWindowModify()
{
    this->setWindowModified(this->document()->isModified());
}

/* 初始化新文档
 * [功能] 创建未命名文档并设置初始属性
 * [流程]
 * 1. 生成带序号默认名称（如"未命名 1"）
 * 2. 设置带[*]占位符的窗口标题
 * 3. 连接文档内容变更信号到状态更新槽 */
void TextEdit::initNewDoc()
{
    docName = QString("未命名 %1").arg(docNo++);
    this->setWindowTitle(docName + "[*]");
}

/* 初始化已打开文档
 * [参数] fileName - 完整文件路径
 * [功能] 解析文件信息并更新窗口属性*/
void TextEdit::initOpenDoc(const QString& fileName)
{
    QFileInfo info(fileName);
    docName = info.fileName();          // 提取纯文件名
    filePath = info.canonicalFilePath(); // 获取规范路径
    this->setWindowTitle(docName + "[*]");
}

/* 文档加载核心方法
 * [参数] fileName - 要加载的文件路径
 * [返回] bool - 是否加载成功
 * [流程]
 * 1. 文件存在性检查
 * 2. 尝试打开文件（只读模式）
 * 3. 读取全部内容
 * 4. 判断文本格式（HTML/纯文本）
 * 5. 初始化文档属性
 * [问题] 直接读取QByteArray可能造成编码错误 */
bool TextEdit::loadDocument(const QString &fileName)
{
    if(fileName.isEmpty()) return false;

    QFile file(fileName);
    if(!file.exists()) return false;

    if(!file.open(QIODevice::ReadOnly)) {
        QMessageBox::warning(this, "错误",
            QString("无法打开文件:\n%1\n错误类型: %2")
                .arg(fileName)
                .arg(file.errorString()));
        return false;
    }

    // 直接读取字节数据（存在编码风险）
    auto text = file.readAll();
    if(Qt::mightBeRichText(text)) {
        this->setHtml(text);
    } else {
        this->setPlainText(text);
    }

    initOpenDoc(fileName);
    file.close();
    return true;
}

// 获取文档显示名称（用于窗口标题）
QString TextEdit::getDocName() const {
    return docName;
}

// 获取规范化的完整文件路径（用于重复打开检查）
QString TextEdit::getFilePath() const {
    return filePath;
}

/*
 * [核心方法] 执行文档保存
 * [返回] bool - 保存是否成功
 * [逻辑]
 * - 已有路径：直接覆盖保存
 * - 新文档：触发另存为流程
 * [注意] 返回值依赖下层方法正确传递
 */
bool TextEdit::saveDoc()
{
    if(!filePath.isEmpty())
        return writeToDoc(filePath);  // 常规保存

   return saveAsDoc();  // 新文档首次保存
}

/*
 * [交互方法] 另存为操作
 * [返回] bool - 保存是否成功
 * [流程]
 * 1. 弹出文件保存对话框
 * 2. 验证文件名有效性
 * 3. 调用写入方法
 * [注意] 对话框取消返回空文件名需处理
 */
bool TextEdit::saveAsDoc()
{
    // 获取带格式过滤的保存路径
    auto fileName = QFileDialog::getSaveFileName(
                this,
                "保存文件",
                QDir::homePath(),  // 默认用户目录
                "HTML文件(*.html);;文本文件(*.txt)"); // 格式过滤

    return writeToDoc(fileName);  // 执行实际写入
}

/**
 * @brief 文档保存提示对话框
 * @return bool
 *         - true : 允许继续操作（保存成功或选择不保存）
 *         - false: 取消当前操作
 *
 * @note 文档未修改时直接返回 true
 */
bool TextEdit::promptSave()
{
    // 检查文档修改状态
    if (!document()->isModified())
        return true;

    // 创建包含文档名的警告消息
    QString msg = QString("%1 已修改，是否保存?").arg(getDocName());

    // 弹出三按钮对话框
    auto btn = QMessageBox::warning(
        this,
        "警告",
        msg,
        QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel
    );

    // 处理用户选择
    if (btn == QMessageBox::Yes) {
        return saveDoc();  // 执行保存操作并返回结果
    } else if (btn == QMessageBox::No) {
        return true;      // 不保存继续操作
    }
    return false;         // 取消当前操作
}

/**
 * @brief 文本编辑窗口关闭事件处理
 * @param event 关闭事件对象
 *
 * @details 安全关闭流程：
 * 1. 通过 promptSave() 检查是否需要保存
 * 2. 根据用户选择决定是否允许关闭
 */
void TextEdit::closeEvent(QCloseEvent* event)
{
    if (promptSave()) {  // 用户确认保存或放弃修改
        event->accept();  // 允许关闭窗口
    } else {              // 用户取消操作
        event->ignore();  // 阻止关闭窗口
    }
}

/*
 * [核心写入方法] 文档持久化存储
 * [参数] fileName - 目标文件路径
 * [返回] bool - 写入结果
 * [流程]
 * 1. 空路径校验
 * 2. 创建文档写入器
 * 3. 执行写入操作
 * 4. 成功时：
 *    - 更新当前文件路径
 *    - 重置修改状态
 *    - 刷新窗口标题状态
 * [问题] 成功时错误返回false（需修正为return true）
 */
bool TextEdit::writeToDoc(const QString &fileName)
{
    if(fileName.isEmpty()) return false;  // 空路径保护

    QTextDocumentWriter docWriter(fileName);  // 创建格式感知写入器
    if(docWriter.write(this->document())) {   // 成功写入
        // 更新持久化路径（规范化处理符号链接等）
        filePath = QFileInfo(fileName).canonicalFilePath();

        // 清除文档修改标志（关键状态变更）
        this->document()->setModified(false);

        // 触发窗口标题更新（去除*修改标记）
        this->setWindowModify();

        return false; // BUG：此处应返回true，导致上层误判失败
    }
    return false;  // 实际写入失败
}
